﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Linq.Expressions;
using System.Data.Entity;

namespace SksApp
{
    public static class Extension
    {
        #region Sayıyı Yazıya Çevirme
        private static String[] birler = { "", "BİR ", "İKİ ", "ÜÇ ", "DÖRT ", "BEŞ ", "ALTI ", "YEDİ ", "SEKİZ ", "DOKUZ " };
        private static String[] onlar = { "", "ON ", "YİRMİ ", "OTUZ ", "KIRK ", "ELLİ ", "ALTMIŞ ", "YETMİŞ ", "SEKSEN ", "DOKSAN " };
        private static String[] binler = { "", "BİN ", "MİLYON ", "MİLYAR ", "TRİLYON " };

        private static String binlik(int x)
        {
            return (x >= 100 ? (x >= 200 ? birler[x / 100] : "") + "YÜZ " : "") + (x % 100 >= 10 ? onlar[((x % 100) / 10)] : "") + birler[x % 10];
        }

        private static String yaziIleEx(long x)
        {
            String str = "";
            String s = "" + x;
            int l = s.Length;//s.length(); // basamak sayisi
            int g = (int)Math.Ceiling(((decimal)l) / 3); // toplam kac tane 3 basamaktan olustugu 48,944,646 => 3
            int t = l % 3 > 0 ? l % 3 : 3; // en yuksek 3'luk grupta kac tane basamak oldugu =>2 (48)
            for (int i = g - 1; i >= 0; i--)
            {
                if (i != g - 1)
                {
                    int d = Int32.Parse(s.Substring((g - i - 2) * 3 + t, 3));
                    str += binlik(d) + (d > 0 ? binler[i] : "");
                }
                else
                {
                    int tmp;
                    String tmpstr;
                    tmpstr = s.Substring(0, t);
                    tmp = Int32.Parse(tmpstr);
                    str += (i != 1 || tmp != 1 ? binlik(tmp) : "") + binler[i];
                }
            }
            if (x == 0)
                str = "sifir";
            return str;
        }

        private static String yaziIle(decimal value)
        {
            decimal kurus = value - Math.Floor(value);
            if (kurus > 0)
                return yaziIleEx((long)Math.Floor(value)) + " TL " + yaziIleEx((long)Math.Floor(kurus * 100)) + " KRŞ";
            else
                return yaziIleEx((long)Math.Floor(value)) + " TL ";
        }

        public static string ToYaziyaCevir(this decimal value)
        {
            return "YALNIZ " + yaziIle(value);
        }
        #endregion

        public static string RemoveTurkis(this string value)
        {
            return value.Replace('İ', 'I').Replace('Ü', 'U').Replace('Ç', 'C').Replace('Ş', 'S').Replace('Ö', 'O').Replace('Ğ', 'G').Replace('ı', 'i').Replace('ü', 'u').Replace('ç', 'c').Replace('ş', 's').Replace('ö', 'o').Replace('ğ', 'g');
        }

        public static string Mid(this string value, int start, int len)
        {
            if (value.Length > start + len)
            {
                return value.Substring(start, len);
            }
            else
            {
                return value.Substring(start);
            }
        }

        public static DateTime ToDatetime(this string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                string[] part1 = value.Split(' ')[0].Split('-');
                string[] part2 = value.Split(' ')[1].Split(':');
                return new DateTime(part1[2].ToInt(), part1[1].ToInt(), part1[0].ToInt(), part2[0].ToInt(), part2[1].ToInt(), part2[2].ToInt());
            }
            else
            {
                return new DateTime(1900, 1, 1);
            }
        }

        public static string ToFormattedString(this DateTime value)
        {
            return string.Format("{0}-{1}-{2} {3}:{4}:{5}", value.Day, value.Month, value.Year, value.Hour, value.Minute, value.Second);
        }

        public static int ToInt(this string value)
        {
            return Cevir.Parse<int>(value);
        }
        public static string Assign(this string value, int len)
        {
            if (value.Length > len)
            {
                return value.Substring(0, len);
            }
            else
            {
                return value + value.Space(len - value.Length);
            }
        }

        public static string Space(this string value, int count)
        {
            string sonuc = "";
            for (int i = 0; i < count; i++)
            {
                sonuc += " ";
            }
            return sonuc;
        }

        public static T ToAnonymousType<T>(this object obj, T prototype) where T : class
        {
            T atiObj = obj as T;
            if (atiObj == null)
            {
                //atiObj = GetTypeInstance(obj, prototype.GetType()) as T;
            }
            return (atiObj);
        }

        public static List<T> CastToList<T>(this object obj, T prototype) where T : class
        {
            List<T> list = new List<T>();
            IEnumerable<T> enumerable = obj as IEnumerable<T>;
            if (enumerable != null)
            {
                list.AddRange(enumerable);
            }
            else
            {
                IEnumerable enumObjects = obj as IEnumerable;
                if (enumObjects == null)
                {
                    return null;
                }
                foreach (object enumObject in enumObjects)
                {
                    T currObject = ToAnonymousType(enumObject, prototype);

                    if (currObject == null)
                    {
                        list.Clear();
                        return list;
                    }
                    list.Add(currObject);
                }
            }
            return list;
        }

        public static T Clone<T>(this object o)
        {
            var newEntityObject = o.GetType().GetConstructor(new Type[0]).Invoke(new object[0]);
            FieldInfo[] myObjectFields = o.GetType().GetFields(
            BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            foreach (FieldInfo fi in myObjectFields)
            {
                fi.SetValue(newEntityObject, fi.GetValue(o));
            }
            return (T)newEntityObject;
        }

        public static Image ResizeBitmap(this Image b, int nWidth, int nHeight)
        {
            Bitmap result = new Bitmap(nWidth, nHeight);
            using (Graphics g = Graphics.FromImage((Image)result))
                g.DrawImage(b, 0, 0, nWidth, nHeight);
            return result;
        }

        public static bool Like(this string s, string pattern, RegexOptions options = RegexOptions.IgnoreCase)
        {
            pattern = Regex.Escape(pattern.Replace('*', '%'));
            pattern = pattern.Replace("%", ".*?").Replace("_", ".");
            pattern = pattern.Replace(@"\[", "[").Replace(@"\]", "]").Replace(@"\^", "^");
            return Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase);
        }

        public static string toStr(this DateTime value)
        {
            return string.Format("{0}.{1}.{2} {3}  {4}:{5}:{6}", value.Day, value.Month, value.Year, GunAdi(value.DayOfWeek), value.Hour, value.Minute, value.Second);
        }

        private static string GunAdi(DayOfWeek gun)
        {
            switch (gun)
            {
                case DayOfWeek.Friday:
                    return "Cuma";
                case DayOfWeek.Monday:
                    return "Pazartesi";
                case DayOfWeek.Saturday:
                    return "Cumartesi";
                case DayOfWeek.Sunday:
                    return "Pazar";
                case DayOfWeek.Thursday:
                    return "Perşembe";
                case DayOfWeek.Tuesday:
                    return "Salı";
                case DayOfWeek.Wednesday:
                    return "Çarşamba";
                default:
                    return "";
            }
        }

        public static void CreateUniqueIndex<TModel>(this Database database, Expression<Func<TModel, object>> expression)
        {
            if (database == null)
                throw new ArgumentNullException("database");

            // Assumes singular table name matching the name of the Model type

            var tableName = typeof(TModel).Name;
            var columnName = GetLambdaExpressionName(expression.Body);
            var indexName = string.Format("IX_{0}_{1}_{2}", tableName, columnName, new Random().Next(1, 10));

            var createIndexSql = string.Format("CREATE UNIQUE INDEX {0} ON {1} ({2})", indexName, tableName, columnName);

            database.ExecuteSqlCommand(createIndexSql);
        }

        public static void CreateIndex<TModel>(this Database database, Expression<Func<TModel, object>> expression)
        {
            if (database == null)
                throw new ArgumentNullException("database");

            // Assumes singular table name matching the name of the Model type

            var tableName = typeof(TModel).Name;
            var columnName = GetLambdaExpressionName(expression.Body);
            var indexName = string.Format("IX_{0}_{1}_{2}", tableName, columnName, new Random().Next(1, 10));

            var createIndexSql = string.Format("CREATE INDEX {0} ON {1} ({2})", indexName, tableName, columnName);

            database.ExecuteSqlCommand(createIndexSql);
        }

        public static string GetLambdaExpressionName(Expression expression)
        {
            MemberExpression memberExp = expression as MemberExpression;

            if (memberExp == null)
            {
                // Check if it is an UnaryExpression and unwrap it
                var unaryExp = expression as UnaryExpression;
                if (unaryExp != null)
                    memberExp = unaryExp.Operand as MemberExpression;
            }

            if (memberExp == null)
                throw new ArgumentException("Cannot get name from expression", "expression");

            return memberExp.Member.Name;
        }
    }
}
